package com.unionftech.content_login.api.interceptor

import okhttp3.Interceptor
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.internal.notifyAll
import okhttp3.internal.wait

class TokenRefreshInterceptor(private val refresh: ITokenRefresh) : Interceptor {
    /**
     * 多个需要刷新token的共享状态
     */
    private var isRefreshing = false

    /**
     * 标记 token 刷新是否失败的共享状态
     */
    private var isRefreshFailed = false

    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()
        // 检查请求头是否包含 Authorization
        val hasAuthorizationHeader = originalRequest.header(refresh.getHeaderTokenKey()) != null

        // 如果不包含 Authorization 请求头，直接放行
        if (!hasAuthorizationHeader) {
            return chain.proceed(originalRequest)
        }
        // 如果包含 Authorization 请求头，继续处理 token 刷新逻辑
        val originalResponse = chain.proceed(originalRequest)
        // 使用 peekBody 读取响应体内容，而不关闭流
        val responseBody = originalResponse.peekBody(Long.MAX_VALUE)
        val responseBodyString = responseBody.string()
        if (isTokenExpired(responseBodyString)) {
            synchronized(this) {
                // 如果 token 刷新失败，直接返回错误响应
                if (isRefreshFailed) {
                    return originalResponse
                }
                //如果正在刷新 token，等待刷新完成
                while (isRefreshing) {
                    try {
                        //等待刷新完成
                        wait()
                    } catch (_: InterruptedException) {
                        Thread.currentThread().interrupt()
                        return originalResponse
                    }
                }
                // 再次检查 token 是否已过期
                if (isTokenExpired(responseBodyString)) {
                    //标记正在进行刷新token
                    isRefreshing = true
                    try {
                        //刷新token
                        val expiredToken = refresh.clearExpiredToken()
                        //需要同步请求
                        val token = refresh.asyncRefreshToken(expiredToken)
                        return if (token != null) {
                            refresh.saveToken(token)
                            // 使用新 token 重新构建请求
                            val newRequest = originalRequest.newBuilder()
                                .header("Authorization", refresh.getAccessToken())
                                .build()
                            // 关闭原始响应
                            originalResponse.close()
                            // 重新发起请求
                            chain.proceed(newRequest)
                        } else {
                            //刷新失败，标记为刷新失败
                            isRefreshFailed = true
                            refresh.needLogin()
                            // 这里可以触发登录逻辑
                            originalResponse
                        }
                    } finally {
                        //标记为刷新完成
                        isRefreshing = false
                        //唤醒所有等待的请求
                        notifyAll()
                    }
                }
            }
        }
        // 如果不需要刷新 token，重新构建一个 Response 供后续逻辑使用
        return originalResponse.newBuilder()
            .body(responseBodyString.toResponseBody(originalResponse.body?.contentType()))
            .build()
    }

    private fun isTokenExpired(responseBodyString: String): Boolean {
        return refresh.isTokenExpired(responseBodyString)
    }
}